Python 写一个简单的FTPv2

**相较上一篇v1的改进版,当前实现了如下功能:
1.上传
2.下载
3.查看server端保存的文件列表
4.上传、下载显示进度条
5.server端将client信息保存为json格式存入本地,实时加载和写入

client code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#Author :ywq
import socket,os,json,sys
import threading
import time

msg_dic={}
size_dic={}
clac_event=threading.Event()

class Scok_Client(object):

def __init__(self):
self.client=socket.socket()

def connect(self,IP,Port):
self.client.connect((IP,Port))

def usage(self):
print(
'''
Usage:action + parameter
Put Filename
Get Filename
Ls
cd ../..
'''
)

def auth(self):
user=input('Input username:')
passwd=input('Input passwd:')
msg_dic['Username']=user
msg_dic['Password']=passwd




def progressbar(self,a,b):
percentage = a/b
num = int(percentage*100)
view = '\r %d%%[%-100s]%d%%'%(0,'#'*num,100)
sys.stdout.write(view)
sys.stdout.flush()


def interactive(self):
while True:
self.auth()
while True:
try:
cmd_str=input('Input cmd:')
cmd=cmd_str.split()[0]
print('Exec action:',cmd )
if hasattr(self,'cmd_%s' %cmd) :
act=getattr(self,'cmd_%s' %cmd)
act(cmd_str)
except Exception as e:
print('Error:',e)
self.usage()


def cmd_put(self,*args):
cmd,filename=args[0].split()
if os.path.isfile(filename):
msg_dic['Action']=cmd
msg_dic['Filename']=filename
file_size=os.path.getsize(filename)
msg_dic[filename+'_Filesize']=file_size
print('\033[1;32mSend Info to Server:\033[0m \n',msg_dic)
self.client.send(json.dumps(msg_dic).encode())
server_ack=self.client.recv(8192)
print('Server ACK:',server_ack)
f=open(filename,'rb')
finished_size=0
start_time=time.time()
clac_start_time=start_time
for line in f:
self.client.send(line)
finished_size+=len(line)
while time.time() - start_time >0.5:
self.progressbar(finished_size,file_size)
start_time=time.time() #print percentage every 0.5 second



print('\033[1;31m%s done,use time:%i seconds\033[0m' %(cmd,time.time()-clac_start_time))
f.close()

def cmd_get(self,*args):
cmd,filename=args[0].split()
msg_dic['Action']=cmd
msg_dic['Filename']=filename
self.client.send(json.dumps(msg_dic).encode())
file_size=int(self.client.recv(8192).decode())
print('\033[1;32mGet File,size:\033[0m',file_size)
self.client.send(b'Client ACK')
f=open(filename,'wb')
finished_size=0
while finished_size < file_size:
data=self.client.recv(8192)
f.write(data)
finished_size+=len(data)
self.progressbar(finished_size,file_size)
else:
print('\033[1;32mReceive done\033[0m',os.stat(filename))
f.close()

def cmd_ls(self,*args):
cmd=args[0].split()[0]
msg_dic['Action']=cmd
self.client.send(json.dumps(msg_dic).encode())
file_list=self.client.recv(8192)
print('\033[1;32mMy file list in server:\033[0m',file_list.decode())


ftp_client=Scok_Client()
ftp_client.connect('localhost',999)
ftp_client.interactive()

server code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#Author :ywq
import socketserver,sys,os,json


client_dic={}
def dic_init(username,password):
client_dic[username]={}
client_dic[username]['file_list']=[]
client_dic[username]['Username']=username
client_dic[username]['Password']=password

dic_init('ywq','qwe')
with open('client_auth.json','w')as auth_conf:
json.dump(client_dic,auth_conf)
'''
save the client auth_info as json_format into local
'''

with open('client_auth.json','r+') as auth_conf:
client_dic=json.load(auth_conf) #load client auth_info

def auth(recv_dic):
client_user=recv_dic['Username']
client_passwd=recv_dic['Password']
if client_user == client_dic[client_user]['Username'] and client_passwd == client_dic[client_user]['Password']:
pass
else:
exit('Auth failed')



class MyHandler(socketserver.BaseRequestHandler):
def handle(self):
while True:
try:
recv_dic=json.loads(self.request.recv(8192).decode())
print('\033[1;31mReceive client dic\033[0m\n',recv_dic)
auth(recv_dic)
client_cmd=recv_dic['Action']
if hasattr(self,'client_%s' %client_cmd ):
exec_cmd=getattr(self,'client_%s' %client_cmd)
exec_cmd(recv_dic)
except Exception as e:
print('Error:',e)


def client_put(self,*args):
recv_dic=args[0]
client_user=recv_dic['Username']
client_dic[client_user].update(recv_dic)
filename=recv_dic['Filename']
filesize=int(recv_dic[filename+'_Filesize'])
print(filesize)
received_size=0
if os.path.isfile(filename):
print('file is already exist')
exit(2)
else:
f=open(filename,'wb')
self.request.send(b'Server ACK')
while received_size < filesize:
data=self.request.recv(8192)
f.write(data)
received_size+=len(data)
else:
print('\033[1;32m Recv done! \033[0m',os.stat(filename))
f.close()
client_dic[client_user]['file_list'].append(filename)
print(client_dic[client_user]['file_list'])
with open('client_auth.json','r+') as auth_conf:
json.dump(client_dic,auth_conf)




def client_get(self,*args):
recv_dic=args[0]
filename=recv_dic['Filename']
file_size=os.stat(filename).st_size #or os.path.getsize()
self.request.send(str(file_size).encode()) #send file size to client
client_ack=self.request.recv(8192)
f=open(filename,'rb')
for line in f:
self.request.send(line)
print('\033[1;32m Send done ,total size:\033[0m',file_size)
f.close()


def client_ls(self,*args):
recv_dic=args[0]
client_user=recv_dic['Username']
user_file_list=client_dic[client_user]['file_list']
self.request.send(str(user_file_list).encode())
print('\033[1;32m Send file_list to user %s:\033[0m' %client_user)



IP,Port='localhost',999
server=socketserver.ThreadingTCPServer((IP,Port),MyHandler)
print('\033[1;32mWaiting for connection:\033[0m')
server.serve_forever()

运行效果:

这里写图片描述

运行完成后的json文件:
这里写图片描述

赏一瓶快乐回宅水吧~
-------------本文结束感谢您的阅读-------------